#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "qcustomplot.h"
#include <QMessageBox>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    difference = new QCustomPlot();
    difference->setFixedSize(400,400);
    difference->show();

    g_x = new QCustomPlot();
    g_x->setFixedSize(400,400);
    g_x->show();
}

MainWindow::~MainWindow()
{
    delete ui;
}

bool MainWindow::event(QEvent *mEvent)
{
    if (mEvent->type()==QEvent::Close)
    {
        difference->close();
        g_x->close();
        this->close();
        return true;
    }
    return QMainWindow::event(mEvent);
}


void MainWindow::plotFunc(QVector<double>& x, QVector<double>& y, QPen color)
{
    ui->graphWidget->clearGraphs();
    ui->graphWidget->addGraph();

    ui->graphWidget->graph(ui->graphWidget->graphCount()-1)->setData(x, y);
    // give the axes some labels:
    ui->graphWidget->xAxis->setLabel("x");
    ui->graphWidget->yAxis->setLabel("y");
    ui->graphWidget->graph(ui->graphWidget->graphCount()-1)->setPen(color);
    ui->graphWidget->xAxis->setRange(0,1);
    //ui->graphWidget->yAxis->setRange(-2.5,2.5);
    //ui->graphWidget->graph(ui->graphWidget->graphCount()-1)->rescaleAxes(true);
    //ui->graphWidget->replot();
}



void MainWindow::plotFunc3(QVector<double>& x, QVector<double>& y, QPen color)
{
    g_x->clearGraphs();
    g_x->addGraph();

    g_x->graph(0)->setData(x, y);
    // give the axes some labels:
    g_x->xAxis->setLabel("x");
    g_x->yAxis->setLabel("g(x)");
    g_x->graph(0)->setPen(color);
    //ui->graphWidget->xAxis->setRange(x[0]-0.5,x[x.size()+1]+0.5);
    //ui->graphWidget->yAxis->setRange(-2.5,2.5);
    //ui->graphWidget->graph(ui->graphWidget->graphCount()-1)->rescaleAxes(true);
    //difference->graph(0)->rescaleAxes();
    g_x->replot();
}
void MainWindow::plotFunc2(QVector<double>& x, QVector<double>& y, QPen color)
{
    //difference->clearGraphs();
    difference->addGraph();

    difference->graph(difference->graphCount()-1)->setData(x, y);
    // give the axes some labels:
    difference->xAxis->setLabel("x");
    difference->yAxis->setLabel("Complexity");
    difference->graph(difference->graphCount()-1)->setPen(color);
    //ui->graphWidget->xAxis->setRange(x[0]-0.5,x[x.size()+1]+0.5);
    //ui->graphWidget->yAxis->setRange(-2.5,2.5);
    //ui->graphWidget->graph(ui->graphWidget->graphCount()-1)->rescaleAxes(true);
    //difference->graph(0)->rescaleAxes();
    difference->replot();
}


double MainWindow::countFunc (double x, int type)
{
    nOperations++;
    double result = 1/(1+x);//(x+1.0)/x;
    if (type==1)
        return result+cos(10*x);
    else if (type==2)
        return result+cos(100*x);
    else if (type==3)
    {
        double A,B;
        A=B=1.0;
        result = 0.0;
        for (int i=1; i<=14; i++)
            result+=A*sin(2*M_PI*x*i*(alpha-t))+B*cos(2*M_PI*x*i*(alpha-t));
    }
    return result;
}

double MainWindow::countIntegral (double a, double b, int type, int method, int n)
{
    if ((method==2) && (n<2))
    {
        n=2;
    }
    nEnteringIntegral++;
    double h=(b-a)/(double)n;
    double result=0.0;

    if (method==0)
    { //Rectangular
        for (int i=0; i<n; i++)
            result += countFunc(a+i*h+h/2, type);
        result*=h;
    }
    else if (method==1)
    { //Trapezoidal
        if (n>1)
        {
            for (int i=1; i<n; i++)
                result += countFunc(a+i*h, type);
        }
        result += (countFunc(a, type) + countFunc(b, type))/2.0;
        result*=h;
    }
    else if (method==2)
    { //Simpson
        for (int i=0; i<n; i+=2)
            result += countFunc(a+i*h, type)+4*countFunc(a+i*h+h, type)+countFunc(a+i*h+2*h, type);
        result*=h/3.0;
    }

    return result;
}

double MainWindow::countAdopted(double a, double b, int method, double eps)
{
    double full = countIntegral(a,b,3,method,1);
    double left = countIntegral(a,(a+b)/2.0,3,method,1);
    double right= countIntegral((b+a)/2.0,b,3,method,1);
    if (fabs(left+right-full)<eps)
    {
        return left+right;
    }
    else
    {
        return countAdopted(a,(a+b)/2.0,method,eps/2.0)+countAdopted((a+b)/2.0,b,method,eps/2.0);
    }
}

void MainWindow::on_pushButton_3_clicked()
{
    ui->graphWidget->clearGraphs();

    int type = -1;
    if (ui->radioButton->isChecked())
        type=0;
    else if (ui->radioButton_2->isChecked())
        type=1;
    else if (ui->radioButton_3->isChecked())
        type=2;
    else if (ui->radioButton_7->isChecked())
        type=3;

    int method=-1;

    if (ui->radioButton_4->isChecked())
        method=0;
    else if (ui->radioButton_5->isChecked())
        method=1;
    else if (ui->radioButton_6->isChecked())
        method=2;

    int n = ui->spinBox->value();
    double eps = ui->doubleSpinBox_ro_2->value();
    alpha = ui->doubleSpinBox_ro->value();

    double a,b,h;
    nOperations = 0;
    int nComputations=0;
    nEnteringIntegral=0;
    double result=0.0;
    double realResult=-1.0;
    t=ui->doubleSpinBox_ro_3->value();

    QVector<double> x(n+1),u(n+1), N(n+1), G(n+1), nCountFunc(n+1);

    if (type!=3)
    {
        a=0;
        b=1;
        h=(b-a)/(double)n;
        realResult = log(2);
        if (type==1) //cos 10x
            realResult += sin(10)/10.0;
        else if (type==2) //cos 100x
            realResult += sin(100)/100.0;

        nOperations = 0;
        result = countIntegral(a, b, type, method, n);
        nComputations= nOperations;
    }
    else
    {
        a=-M_PI_2;
        b=M_PI_2;
        double A=0.0, B=1.0;
        h=(B-A)/(double)n;


        for (int i=0; i<n+1; i++)
        {
            x[i]=A+i*h;
        }


        realResult = 0.0;
        double B_param=1;

        if (fabs(t-alpha)<1e-5)
        {
            realResult = 14.0 * B_param * M_PI;
        }
        else
        {
            for (int i=1; i<=14; i++)
            {
                    realResult+=sin(M_PI*M_PI*i*(alpha-t))/(i);
            }
            realResult*=B_param/(M_PI*(alpha-t));
        }

        nOperations = 0;
        result = countAdopted(a, b, method, eps);


        nComputations = nOperations;
        for (int i=0; i<n+1; i++)
        {
            nOperations = 0;
            nEnteringIntegral=0;
            t=x[i];
            G[i] = countAdopted(a, b, method, eps);
            N[i]=nEnteringIntegral;
            nCountFunc[i] = nOperations;
        }
        difference->clearGraphs();
        plotFunc2(x,N);
        plotFunc2(x,nCountFunc, QPen(Qt::red));
        difference->graph(0)->rescaleAxes();
        difference->graph(1)->rescaleAxes();
        difference->replot();
        plotFunc3(x,G, QPen(Qt::red));
        g_x->graph(0)->rescaleAxes();
        g_x->replot();
    }


    h=(b-a)/(double)n;
    t=ui->doubleSpinBox_ro_3->value();

    for (int i=0; i<n+1; i++)
    {
        x[i]=a+i*h;
        u[i]=countFunc(x[i], type);
    }
    plotFunc(x,u);

    QString text = "Computed integral value is %1.\n Accuracy is %2\nN of computations is %3\nRealIntegralValue is %4";
    text = text.arg(result).arg(result-realResult).arg(nComputations).arg(realResult);

    ui->label_14->setText(text);

    QMessageBox msgBox;
    msgBox.setText(text);
    msgBox.exec();

    //ui->graphWidget->graph(0)->rescaleAxes(true);

    ui->graphWidget->graph(0)->rescaleAxes();
    ui->graphWidget->replot();
}

void MainWindow::on_pushButton_loadValues_clicked()
{
}
